home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / MacMud / Mud 4.0 / lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-22  |  35.2 KB  |  1,769 lines  |  [TEXT/MPS ]

  1. #include <quickdraw.h>
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <FCntl.h>
  6. #include <mac.h>
  7. #include <packages.h>
  8. #include <cursorctl.h>
  9. #include "instrs.h"
  10. #include "lint.h"
  11. #include "lang.h"
  12. #include "string.h"
  13. #include "config.h"
  14. #include "interpret.h"
  15. #include "exec.h"
  16. #include "lex.h"
  17. #include "nlhack.h"
  18.  
  19. #if defined(__GNUC__) && !defined(lint)
  20. #define INLINE inline
  21. #else
  22. #define INLINE
  23. #endif
  24.  
  25. #define isalunum(c) (isalnum(c) || (c) == '_')
  26. #define NELEM(a) (sizeof (a) / sizeof (a)[0])
  27.  
  28. int current_line;
  29. int total_lines;    /* Used to compute average compiled lines/s */
  30. char *current_file;
  31. int pragma_strict_types;    /* Force usage of strict types. */
  32. int pragma_save_types;        /* Save argument types after compilation */
  33. struct lpc_predef_s *lpc_predefs=NULL;
  34. extern char *argument_name;
  35. extern char *xalloc();
  36. static int number PROT((int)), ident PROT((char *)), string PROT((char *));
  37. static int islocal PROT((char *));
  38. static void handle_define PROT((char *));
  39. static void free_defines PROT((void)), add_define PROT((char *, int, char *));
  40. static int expand_define PROT((void));
  41. static void add_input PROT((char *));
  42. static void myungetc PROT((int));
  43. static int lookup_resword PROT((char *));
  44. static int cond_get_exp PROT((int));
  45. static int exgetc();
  46. static FILE *yyin;
  47. static int lex_fatal;
  48. static char **inc_list;
  49. static int inc_list_size;
  50.  
  51. extern void LPEvents(void);
  52. extern void LPSetBusy(void);
  53. extern void LPClearBusy(void);
  54. extern Boolean gLexActive;
  55.  
  56. #define WNETICKINTERVAL 8
  57. #define EXPANDMAX 25000
  58. static int nexpands;
  59.  
  60. extern char **local_names;
  61. extern int current_number_of_locals;
  62.  
  63. extern char *string_copy();
  64.  
  65. #ifndef tolower
  66. extern int tolower PROT((int));
  67. #endif
  68.  
  69. void yyerror(), error(), free();
  70.  
  71. #define MAXLINE 1024
  72. static char yytext[MAXLINE];
  73. static int slast, lastchar;
  74.  
  75. struct defn {
  76.     struct defn *next;
  77.     char *name;
  78.     int undef;
  79.     char *exps;
  80.     int nargs;
  81. };
  82. struct defn *lookup_define();
  83.  
  84. static struct ifstate {
  85.     struct ifstate *next;
  86.     int state;
  87. } *iftop = 0;
  88. #define EXPECT_ELSE 1
  89. #define EXPECT_ENDIF 2
  90.  
  91. static struct incstate {
  92.     struct incstate *next;
  93.     FILE *yyin;
  94.     int line;
  95.     char *file;                /* file name */
  96. #if 0
  97.     char *buffer;            /* token buffer */
  98.     int charsdone;
  99.     int charsread;
  100. #endif
  101.     int slast, lastchar;
  102.     int pragma_strict_types;
  103. } *inctop = 0;
  104.  
  105. #define DEFMAX 10000
  106. static char defbuf[DEFMAX];
  107. static int nbuf;
  108. static char *outp;
  109.  
  110. void merge(name, dest)
  111.     char *name, *dest;
  112. {
  113.     char *from;
  114.  
  115.     strcpy(dest, current_file);
  116.     if (from = strrchr(dest, '/'))   /* strip filename */
  117.     *from = 0;
  118.     else
  119.     /* current_file was the file_name */
  120.     /* include from the root directory */
  121.     *dest = 0;
  122.  
  123.     from = name;
  124.     while (*from == '/') {
  125.     from++;
  126.     *dest=0;    /* absolute path */
  127.     }
  128.  
  129.     while(*from) {
  130.     if(!strncmp(from, "../", 3)) {
  131.         char *tmp;
  132.         
  133.         if(*dest == 0) /* including from above mudlib is NOT allowed */
  134.         break;
  135.         tmp = strrchr(dest, '/');
  136.         if(tmp == NULL) /* 1 component in dest */
  137.         *dest = 0;
  138.         else
  139.         *tmp = 0;
  140.         from +=3;   /* skip "../" */
  141.     }
  142.     else if(!strncmp(from, "./", 2)) {
  143.         from += 2;
  144.     }
  145.     else { /* append first component to dest */
  146.         char *q;
  147.         
  148.         if(*dest)
  149.         strcat(dest, "/");    /* only if dest is not empty !! */
  150.         q = strchr(from, '/');
  151.         
  152.         if(q) { /* from has 2 or more components */
  153.         while(*from=='/') /* find the start */
  154.             from++;
  155.         strncat(dest, from, q - from);
  156.         for(from = q+1;*from=='/';from++)
  157.             ;
  158.         }
  159.         else {
  160.         /* this was the last component */
  161.         strcat(dest, from);
  162.         break;
  163.         }
  164.     }
  165.     }
  166. }
  167.  
  168. static INLINE int
  169. mygetc()
  170. {
  171.     int c;
  172.  
  173.     if (nbuf) {
  174.         nbuf--;
  175.         c = *outp++;
  176.     } else {
  177.         c = getc(yyin);
  178.     }
  179.     lastchar = slast;
  180.     slast = c;
  181. /*fprintf(stderr, "c='%c'", c);*/
  182.     return c;
  183. }
  184.  
  185. static INLINE int
  186. gobble(c)
  187. int c;
  188. {
  189.     int d;
  190.  
  191.     d = mygetc();
  192.     if (c == d)
  193.     return 1;
  194.     *--outp = d;
  195.     nbuf++;
  196.     return 0;
  197. }
  198.  
  199. static void
  200. lexerror(s)
  201. char *s;
  202. {
  203.     yyerror(s);
  204.     lex_fatal++;
  205. }
  206.  
  207. static int
  208. skip_to(token, atoken)
  209. char *token, *atoken;
  210. {
  211.     char b[20], *p;
  212.     int c;
  213.     int nest;
  214.  
  215.     for(nest = 0;;) {
  216.     c = mygetc();
  217.     if (c == '#') {
  218.         do {
  219.         c = mygetc();
  220.         } while(isspace(c));
  221.         for(p = b; c != '\n' && c != EOF; ) {
  222.         if (p < b+sizeof b-1)
  223.             *p++ = c;
  224.         c = mygetc();
  225.         }
  226.         *p++ = 0;
  227.         for(p = b; *p && !isspace(*p); p++)
  228.         ;
  229.         *p = 0;
  230. /*fprintf(stderr, "skip checks %s\n", b);*/
  231.         if (strcmp(b, "if") == 0 || strcmp(b, "ifdef") == 0 ||
  232.         strcmp(b, "ifndef") == 0) {
  233.         nest++;
  234.         } else if (nest > 0) {
  235.         if (strcmp(b, "endif") == 0)
  236.             nest--;
  237.         } else {
  238.         if (strcmp(b, token) == 0)
  239.             return 1;
  240.         else if (atoken && strcmp(b, atoken) == 0)
  241.             return 0;
  242.         }
  243.     } else {
  244. /*fprintf(stderr, "skipping (%d) %c", c, c);*/
  245.             while (c != '\n' && c != EOF) {
  246.         c = mygetc();
  247. /*fprintf(stderr, "%c", c);*/
  248.         } 
  249.         if (c == EOF) {
  250.         lexerror("Unexpected end of file while skipping");
  251.         return 1;
  252.         }
  253.     }
  254.     if (inctop == 0)
  255.         store_line_number_info();
  256.     current_line++;
  257.     total_lines++;
  258.     }
  259. }
  260.  
  261. static void
  262. handle_cond(c)
  263. int c;
  264. {
  265.     struct ifstate *p;
  266.  
  267. /*fprintf(stderr, "cond %d\n", c);*/
  268.     if (c || skip_to("else", "endif")) {
  269.     p = (struct ifstate *)xalloc(sizeof(struct ifstate));
  270.     p->next = iftop;
  271.     iftop = p;
  272.     p->state = c ? EXPECT_ELSE : EXPECT_ENDIF;
  273.     }
  274.     if (!c) {
  275.     if (inctop == 0)
  276.         store_line_number_info();
  277.     current_line++;
  278.     total_lines++;
  279.     }
  280. }
  281.  
  282. static FILE *
  283. inc_open(buf, name)
  284.     char *buf, *name;
  285. {
  286.     int i;
  287.     char *p;
  288.     FILE *f;
  289.  
  290.     merge(name, buf);
  291.     if ((f = fopen(buf, "r")) != NULL)
  292.         return f;
  293.     /*
  294.      * Search all include dirs specified.
  295.      */
  296.     for (p=strchr(name, '.'); p; p = strchr(p+1, '.')) {
  297.     if (p[1] == '.')
  298.         return NULL;
  299.     }
  300.     for (i=0; i < inc_list_size; i++) {
  301.         sprintf(buf, inc_list[i], name);
  302.         if ((f = fopen(buf, "r")) != NULL)
  303.             return f;
  304.     }
  305.     return NULL;
  306. }
  307.  
  308. static void
  309. handle_include(name)
  310. char *name;
  311. {
  312.     FILE *f;
  313.     char *p;
  314.     char buf[1024];
  315.     struct incstate *is;
  316.     int delim;
  317.  
  318. /*fprintf(stderr, "handle include '%s'\n", name);*/
  319.     if (nbuf) {
  320.     lexerror("Internal preprocessor error");
  321.     return;
  322.     }
  323.     if (*name != '"' && *name != '<') {
  324.     struct defn *d;
  325.     if ((d = lookup_define(name)) && d->nargs == -1) {
  326.         char *q;
  327.         q = d->exps;
  328.         while(isspace(*q))
  329.         q++;
  330.         handle_include(q);
  331.     } else {
  332.         yyerror("Missing leading \" or < in #include");
  333.     }
  334.     return;
  335.     }
  336.     delim = *name++ == '"' ? '"' : '>';
  337.     for(p = name; *p && *p != delim; p++)
  338.     ;
  339.     if (!*p) {
  340.     yyerror("Missing trailing \" or > in #include");
  341.     return;
  342.     }
  343.     if (strlen(name) > sizeof(buf) - 100) {
  344.     yyerror("Include name too long.");
  345.     return;
  346.     }
  347.     *p = 0;
  348.     if ((f = inc_open(buf, name)) != NULL) {
  349.     is = (struct incstate *)xalloc(sizeof(struct incstate));
  350.     is->yyin = yyin;
  351.     is->line = current_line;
  352.     is->file = current_file;
  353.     is->slast = slast;
  354.     is->lastchar = lastchar;
  355.     is->next = inctop;
  356.     is->pragma_strict_types = pragma_strict_types;
  357.     pragma_strict_types = 0;
  358.     inctop = is;
  359.     current_line = 1;
  360.     current_file = xalloc(strlen(buf)+1);
  361.     strcpy(current_file, buf);
  362.     slast = lastchar = '\n';
  363.     yyin = f;
  364. /*fprintf(stderr, "pushed to %s\n", buf);*/
  365.     } else {
  366.     sprintf(buf, "Cannot #include %s\n", name);
  367.     yyerror(buf);
  368.     }
  369. }
  370.  
  371. static void
  372. skip_comment()
  373. {
  374.     int c;
  375.  
  376.     for(;;) {
  377.     while((c = mygetc()) != '*') {
  378.         if (c == EOF) {
  379.             lexerror("End of file in a comment");
  380.             return;
  381.         }
  382.         if (c == '\n') {
  383.             if (inctop == 0)
  384.                 store_line_number_info();
  385.             nexpands=0;
  386.             current_line++;
  387.         }
  388.     }
  389.     do {
  390.         c = mygetc();
  391.         if (c == '/')
  392.             return;
  393.         if (c == '\n') {
  394.             if (inctop == 0)
  395.                 store_line_number_info();
  396.             nexpands=0;
  397.             current_line++;
  398.         }
  399.     } while(c == '*');
  400.     }
  401. }
  402.  
  403. #define TRY(c, t) if (gobble(c)) return t
  404.  
  405. static void
  406. deltrail(sp)
  407. char *sp;
  408. {
  409.     char *p;
  410.     p = sp;
  411.     if (!*p) {
  412.     lexerror("Illegal # command");
  413.     } else {
  414.     while(*p && !isspace(*p))
  415.         p++;
  416.     *p = 0;
  417.     }
  418. }
  419.  
  420. #define SAVEC \
  421.     if (yyp < yytext+MAXLINE-5)\
  422.        *yyp++ = c;\
  423.     else {\
  424.        lexerror("Line too long");\
  425.        break;\
  426.     }
  427.  
  428. static void handle_pragma(str)
  429.     char *str;
  430. {
  431.     if (strcmp(str, "strict_types") == 0) {
  432.     pragma_strict_types = 1;
  433.     } else if (strcmp(str, "save_types") == 0) {
  434.     pragma_save_types = 1;
  435.     }
  436. }
  437.  
  438. static int
  439. yylex1()
  440. {
  441.   char *yyp;
  442.   int c;
  443.  
  444.   for(;;) {
  445.     if (lex_fatal) {
  446.     return -1;
  447.     }
  448.     switch((c = mygetc())) {
  449.     case EOF:
  450.     if (inctop) {
  451.         struct incstate *p;
  452.         p = inctop;
  453.         fclose(yyin);
  454. /*fprintf(stderr, "popping to %s\n", p->file);*/
  455.         xfree(current_file);
  456.         nexpands=0;
  457.         current_file = p->file;
  458.         current_line = p->line + 1;
  459.         pragma_strict_types = p->pragma_strict_types;
  460.         yyin = p->yyin;
  461.         slast = p->slast;
  462.         lastchar = p->lastchar;
  463.         inctop = p->next;
  464.         if (inctop == 0)
  465.         store_line_number_info();
  466.         xfree((char *)p);
  467.         break;
  468.     }
  469.     if (iftop) {
  470.         struct ifstate *p = iftop;
  471.         yyerror(p->state == EXPECT_ENDIF ? "Missing #endif" : "Missing #else");
  472.         while(iftop) {
  473.         p = iftop;
  474.         iftop = p->next;
  475.         xfree((char *)p);
  476.         }
  477.     }
  478.     return -1;
  479.     case '\n':
  480.     {
  481.         if (inctop == 0)
  482.         store_line_number_info();
  483.         nexpands=0;
  484.         current_line++;
  485.         total_lines++;
  486.     }
  487.     case ' ':
  488.     case '\t':
  489.     case '\f':
  490.     case '\v':
  491.     break;
  492.     case '+':
  493.     TRY('+', F_INC);
  494.     TRY('=', F_ADD_EQ);
  495.     return c;
  496.     case '-':
  497.     TRY('>', F_ARROW);
  498.     TRY('-', F_DEC);
  499.     TRY('=', F_SUB_EQ);
  500.     return c;
  501.     case '&':
  502.     TRY('&', F_LAND);
  503.     TRY('=', F_AND_EQ);
  504.     return c;
  505.     case '|':
  506.     TRY('|', F_LOR);
  507.     TRY('=', F_OR_EQ);
  508.     return c;
  509.     case '^':
  510.     TRY('=', F_XOR_EQ);
  511.     return c;
  512.     case '<':
  513.     if (gobble('<')) {
  514.         TRY('=', F_LSH_EQ);
  515.         return F_LSH;
  516.     }
  517.     TRY('=', F_LE);
  518.     return c;
  519.     case '>':
  520.     if (gobble('>')) {
  521.         TRY('=', F_RSH_EQ);
  522.         return F_RSH;
  523.     }
  524.     TRY('=', F_GE);
  525.     return c;
  526.     case '*':
  527.     TRY('=', F_MULT_EQ);
  528.     return c;
  529.     case '%':
  530.     TRY('=', F_MOD_EQ);
  531.     return c;
  532.     case '/':
  533.     if (gobble('*')) {
  534.         skip_comment();
  535.         break;
  536.         }
  537.     TRY('=', F_DIV_EQ);
  538.     return c;
  539.     case '=':
  540.     TRY('=', F_EQ);
  541.     return c;
  542.     case ';':
  543.     case '(':
  544.     case ')':
  545.     case ',':
  546.     case '{':
  547.     case '}':
  548.     case '~':
  549.     case '[':
  550.     case ']':
  551.     case '?':
  552.     return c;
  553.     case '!':
  554.     TRY('=', F_NE);
  555.     return F_NOT;
  556.     case ':':
  557.     TRY(':', F_COLON_COLON);
  558.     return ':';
  559.     case '.':
  560.     TRY('.',F_RANGE);
  561.     goto badlex;
  562.     case '#':
  563.     if (lastchar == '\n') {
  564.         char *sp = 0;
  565.         int quote;
  566.  
  567.         yyp = yytext;
  568.         do {
  569.             c = mygetc();
  570.         } while (isspace(c));
  571.         for(quote = 0;;) {
  572.  
  573.         if (c == '"')
  574.             quote ^= 1;
  575.         while(!quote && c == '/') { /*gc - handle comments cpp-like! 1.6.91 @@@*/
  576.             if(gobble('*')) { 
  577.             skip_comment();
  578.             c = mygetc();
  579.             } else 
  580.             break;
  581.         }
  582.  
  583.         if (!sp && isspace(c))
  584.             sp = yyp;
  585.         if (c == '\n' || c == EOF)
  586.             break;
  587.         SAVEC;
  588.         c = mygetc();
  589.         }
  590.         if (sp) {
  591.         *sp++ = 0;
  592.         while(isspace(*sp))
  593.             sp++;
  594.         } else {
  595.         sp = yyp;
  596.         }
  597.         *yyp = 0;
  598.         if (strcmp("define", yytext) == 0) {
  599.         handle_define(sp);
  600.         } else if (strcmp("if", yytext) == 0) {
  601. #if 0
  602.         short int nega=0; /*@@@ allow #if !VAR gc 1.6.91*/
  603.         if (*sp=='!'){ sp++; nega=1;}
  604.         if (isdigit(*sp)) {
  605.             char *p;
  606.             long l;
  607.             l = strtol(sp, &p, 10);
  608.             while(isspace(*p))
  609.             p++;
  610.             if (*p)
  611.             yyerror("Condition too complex in #if");
  612.             else
  613.             handle_cond(nega?!(int)l:(int)l);
  614.         } else if (isalunum(*sp)) {
  615.             char *p = sp;
  616.             while(isalunum(*p))
  617.             p++;
  618.             if (*p) {
  619.             *p++ = 0;
  620.             while(isspace(*p))
  621.                 p++;
  622.             }
  623.             if (*p)
  624.             yyerror("Condition too complex in #if");
  625.             else {
  626.             struct defn *d;
  627.             d = lookup_define(sp);
  628.             if (d) {
  629.                 handle_cond(nega?!atoi(d->exps):atoi(d->exps));/* a hack! */
  630.             } else {
  631.                 handle_cond(nega?1:0); /* cpp-like gc*/
  632.             }
  633.             }
  634.         } else
  635.             yyerror("Condition too complex in #if");
  636. #else
  637.         int cond;
  638.  
  639.         myungetc(0);
  640.         add_input(sp);
  641.         cond=cond_get_exp(0);
  642.  
  643.         if (mygetc()) {
  644.             yyerror("Condition too complex in #if");
  645.             while (mygetc()) ;
  646.         } else
  647.             handle_cond(cond);
  648. #endif
  649.         } else if (strcmp("ifdef", yytext) == 0) {
  650.         deltrail(sp);
  651.         handle_cond(lookup_define(sp) != 0);
  652.         } else if (strcmp("ifndef", yytext) == 0) {
  653.         deltrail(sp);
  654.         handle_cond(lookup_define(sp) == 0);
  655.         } else if (strcmp("else", yytext) == 0) {
  656.         if (iftop && iftop->state == EXPECT_ELSE) {
  657.             struct ifstate *p = iftop;
  658.  
  659. /*fprintf(stderr, "found else\n");*/
  660.             iftop = p->next;
  661.             xfree((char *)p);
  662.             skip_to("endif", (char *)0);
  663.             current_line++;
  664.             total_lines++;
  665.         } else {
  666.             yyerror("Unexpected #else");
  667.         }
  668.         } else if (strcmp("endif", yytext) == 0) {
  669.         if (iftop && (iftop->state == EXPECT_ENDIF ||
  670.                   iftop->state == EXPECT_ELSE)) {
  671.             struct ifstate *p = iftop;
  672.  
  673. /*fprintf(stderr, "found endif\n");*/
  674.             iftop = p->next;
  675.             xfree((char *)p);
  676.         } else {
  677.             yyerror("Unexpected #endif");
  678.         }
  679.         } else if (strcmp("undef", yytext) == 0) {
  680.         struct defn *d;
  681.  
  682.         deltrail(sp);
  683.         if (d = lookup_define(sp))
  684.             d->undef++;
  685.         } else if (strcmp("echo", yytext) == 0) {
  686.         fprintf(stderr, "%s\n", sp);
  687.         } else if (strcmp("include", yytext) == 0) {
  688. /*fprintf(stderr, "including %s\n", sp);        */
  689.                 handle_include(sp);
  690.         } else if (strcmp("pragma", yytext) == 0) {
  691.         handle_pragma(sp);
  692.         } else {
  693.         yyerror("Unrecognised # directive");
  694.         }
  695.         myungetc('\n');
  696.         break;
  697.     } else
  698.         goto badlex;
  699.     case '\'':
  700.     yylval.number = mygetc();
  701.     if (yylval.number == '\\')
  702.         yylval.number = mygetc();
  703.     if (!gobble('\''))
  704.         yyerror("Illegal character constant");
  705.     return F_NUMBER;
  706.     case '"':
  707.     yyp = yytext;
  708.     *yyp++ = c;
  709.     for(;;) {
  710.         c = mygetc();
  711.         if (c == EOF) {
  712.          lexerror("End of file in string");
  713.         return string("\"\"");
  714.         } else if (c == '\n') {
  715.          lexerror("Newline in string");
  716.         return string("\"\"");
  717.         }
  718.         SAVEC;
  719.         if (c == '"')
  720.         break;
  721.         if (c == '\\') {
  722.         c = mygetc();
  723.         if ( c == '\n' ) {
  724.             yyp--;
  725.             if (inctop == 0)
  726.                 store_line_number_info();
  727.             current_line++;
  728.             total_lines++;
  729.         } else if ( c == EOF ) {
  730.             myungetc(c); /* some operating systems give EOF only once */
  731.         } else *yyp++ = c;
  732.         }
  733.     }
  734.     *yyp = 0;
  735.     return string(yytext);
  736.  
  737.     case '0':
  738.     c = mygetc();
  739.     if (c == 'X' || c == 'x') {
  740.         yyp=yytext;
  741.         for(;;) {
  742.         c = mygetc();
  743.         SAVEC;
  744.         if (!isxdigit(c))
  745.             break;
  746.         }
  747.         myungetc(c);
  748.         return number( (int)strtol(yytext,(char**)NULL,0x10) );
  749.     }
  750.     myungetc(c);
  751.     c = '0';
  752.     /* fall through */
  753.              case '1':case '2':case '3':case '4':
  754.     case '5':case '6':case '7':case '8':case '9':
  755.     yyp = yytext;
  756.     *yyp++ = c;
  757.     for(;;) {
  758.         c = mygetc();
  759.         if (!isdigit(c))
  760.         break;
  761.         SAVEC;
  762.     }
  763.     myungetc(c);
  764.     *yyp = 0;
  765.     return number(atoi(yytext));
  766.     default:
  767.     if (isalpha(c) || c == '_') {
  768.         int r;
  769.  
  770.         yyp = yytext;
  771.         *yyp++ = c;
  772.         for(;;) {
  773.         c = mygetc();
  774.         if (!isalunum(c))
  775.             break;
  776.         SAVEC;
  777.         }
  778.         *yyp = 0;
  779.  
  780.         myungetc(c);
  781.         if (!expand_define()) {
  782.         r = lookup_resword(yytext);
  783.         if (r >= 0) {
  784.             return r;
  785.         } else
  786.             return ident(yytext);
  787.         }
  788.         break;
  789.         }
  790.     goto badlex;
  791.     }
  792.   }
  793.  badlex:
  794.   { char buff[100]; sprintf(buff, "Illegal character (hex %02x) '%c'", c, c);
  795.     yyerror(buff); return ' '; }
  796. }
  797.  
  798. int yylex()
  799. {
  800.     int r;
  801.     long thissec;
  802.     static long lastsec = 0;
  803.     extern Boolean gLexActive;
  804.  
  805.     thissec = TickCount();
  806.     if (thissec > lastsec + WNETICKINTERVAL ||
  807.         thissec < lastsec - WNETICKINTERVAL)
  808.     {
  809.         gLexActive = true;
  810.         LPEvents();
  811.         gLexActive = false;
  812.         SpinCursor(8);
  813.         lastsec = TickCount();
  814.     }
  815.     yytext[0] = 0;
  816.     r = yylex1();
  817. /*    fprintf(stderr, "lex=%d(%s) ", r, yytext);*/
  818.     return r;
  819. }
  820.  
  821. extern YYSTYPE yylval;
  822.  
  823. static int islocal(str)
  824.     char *str;
  825. {
  826.     int i;
  827.  
  828.     for (i=current_number_of_locals-1; i>=0; i--) {
  829.     if (strcmp(local_names[i], str) == 0)
  830.             return i;
  831.     }
  832.     return -1;
  833. }
  834.  
  835. static int ident(str)
  836.     char *str;
  837. {
  838.     int i;
  839.    
  840.     i = islocal(str);
  841.     if (i >= 0) {
  842.         yylval.number = i;
  843.         return F_LOCAL_NAME;
  844.     }
  845.     yylval.string = string_copy(str);
  846.     return F_IDENTIFIER;
  847. }
  848.  
  849. static int string(str)
  850.     char *str;
  851. {
  852.     char *p;
  853.  
  854.     if (!*str) {
  855.     str = "\"\"";
  856.     }
  857.     p = xalloc(strlen(str));
  858.     yylval.string = p;
  859.     for (str++; str[0] && str[1] ; str++, p++) {
  860.     if (str[0] == '\\') {
  861.         if (str[1] == 'n') {
  862.         *p = '\n';
  863.         } else if (str[1] == 't') {
  864.         *p = '\t';
  865.         } else if (str[1] == 'r') {
  866.         *p = '\r';
  867.         } else if (str[1] == 'b') {
  868.         *p = '\b';
  869.         } else
  870.         *p = str[1];
  871.         str++;
  872.     } else
  873.         *p = *str;
  874.     }
  875.     *p = '\0';
  876.     return F_STRING;
  877. }
  878.  
  879. static int number(i)
  880.     int i;
  881. {
  882.     yylval.number = i;
  883.     return F_NUMBER;
  884. }
  885.  
  886. void end_new_file()
  887. {
  888.     while (inctop) {
  889.         struct incstate *p;
  890.  
  891.         p = inctop;
  892.         fclose(yyin);
  893.         xfree(current_file);
  894.         current_file = p->file;
  895.         yyin = p->yyin;
  896.         inctop = p->next;
  897.         xfree((char *)p);
  898.     }
  899.     while(iftop) {
  900.         struct ifstate *p;
  901.  
  902.         p = iftop;
  903.         iftop = p->next;
  904.         xfree((char *)p);
  905.     }
  906.     SetCursor(&qd.arrow);
  907.     LPClearBusy();
  908. }
  909.  
  910. #if 0
  911. /*
  912.  * Files for which the standard include file should NOT be included
  913.  */
  914. static char *exclude_files[] = {
  915.     "secure/master.c",
  916.     "obj/master.c",
  917.     "obj/simul_efun.c",
  918.     "std/object.c"
  919. };
  920. #endif
  921.  
  922. void start_new_file(f, level)
  923.     FILE *f;
  924.     int level;
  925. {
  926.     int i;
  927.     static std_include[NSIZE];
  928.     struct lpc_predef_s *tmpf;
  929.  
  930.     free_defines();
  931.     add_define("LPC3", -1, "");
  932. #ifdef COMPAT_MODE
  933.     add_define("COMPAT_FLAG", -1, "");
  934. #endif
  935.     for (tmpf=lpc_predefs; tmpf; tmpf=tmpf->next) {
  936.     char namebuf[NSIZE];
  937.     char mtext[MLEN];
  938.  
  939.     *mtext='\0';
  940.     sscanf(tmpf->flag,"%[^=]=%[ -~=]",namebuf,mtext);
  941.     if (strlen(namebuf) >= NSIZE) fatal("NSIZE exceeded");
  942.     if (strlen(mtext) >= MLEN) fatal("MLEN exceeded");
  943.     add_define(namebuf,-1,mtext);
  944.     }
  945.     yyin = f;
  946.     slast = '\n';
  947.     lastchar = '\n';
  948.     current_line = 1;
  949.     lex_fatal = 0;
  950.     nbuf = 0;
  951.     outp = defbuf+DEFMAX;
  952.     pragma_strict_types = 0;        /* I would prefer !o_flag   /Lars */
  953.     nexpands = 0;
  954.  
  955.     LPSetBusy();
  956. #if 0
  957.     for (i = 0 ; i < (sizeof (exclude_files) / sizeof (char *)); i++)
  958.     if (!strcmp(exclude_files[i], current_file))
  959.         return;
  960.     strcpy(std_include, FORCE_INCLUDE);
  961.     handle_include(std_include);
  962.     current_line = 1;
  963.     if (level) return;
  964.     /*
  965.      * If you get here, you're not in an inherited file. Not used at this
  966.      * moment (the assumption is not safe at all).
  967.      */
  968. #endif
  969. }
  970.  
  971. /*
  972.  * The number of arguments stated below, are used by the compiler.
  973.  * If min == max, then no information has to be coded about the
  974.  * actual number of arguments. Otherwise, the actual number of arguments
  975.  * will be stored in the byte after the instruction.
  976.  * A maximum value of -1 means unlimited maximum value.
  977.  *
  978.  * If an argument has type 0 (T_INVALID) specified, then no checks will
  979.  * be done at run time.
  980.  *
  981.  * The argument types are currently not checked by the compiler,
  982.  * only by the runtime.
  983.  */
  984. static struct keyword {
  985.     char *word;
  986.     short  token;
  987.     short min_args;    /* Minimum number of arguments. */
  988.     short max_args;    /* Maximum number of arguments. */
  989.     short ret_type;    /* The return type used by the compiler. */
  990.     char arg_type1;    /* Type of argument 1 */
  991.     char arg_type2;    /* Type of argument 2 */
  992.     char arg_index;    /* Index pointing to where to find arg type */
  993.     short Default;      /* an efun to use as default for last argument */
  994. } predefs[] =
  995. #include "efun_defs.c"
  996.  
  997. static struct keyword reswords[] = {
  998. { "break",        F_BREAK, },
  999. { "case",        F_CASE, },
  1000. { "catch",        F_CATCH, },
  1001. { "continue",        F_CONTINUE, },
  1002. { "default",        F_DEFAULT, },
  1003. { "do",            F_DO, },
  1004. { "else",        F_ELSE, },
  1005. { "for",        F_FOR, },
  1006. { "if",            F_IF, },
  1007. { "inherit",        F_INHERIT, },
  1008. { "int",        F_INT, },
  1009. { "mapping",        F_MAPPING, },
  1010. { "mixed",        F_MIXED, },
  1011. { "nomask",        F_NO_MASK, },
  1012. { "object",        F_OBJECT, },
  1013. { "parse_command",    F_PARSE_COMMAND, },
  1014. { "private",        F_PRIVATE, },
  1015. { "protected",        F_PROTECTED, },
  1016. { "public",        F_PUBLIC, },
  1017. { "return",        F_RETURN, },
  1018. { "sscanf",        F_SSCANF, },
  1019. { "static",        F_STATIC, },
  1020. { "status",        F_STATUS, },
  1021. { "string",        F_STRING_DECL, },
  1022. { "switch",        F_SWITCH, },
  1023. { "varargs",        F_VARARGS, },
  1024. { "void",        F_VOID, },
  1025. { "while",        F_WHILE, },
  1026. };
  1027.  
  1028. struct instr instrs[256];
  1029.  
  1030. static void add_instr_name(name, n)
  1031.     char *name;
  1032.     int n;
  1033. {
  1034.     instrs[n - F_OFFSET].name = name;
  1035. }
  1036.  
  1037. void init_num_args()
  1038. {
  1039.     int i, n;
  1040.  
  1041.     for(i=0; i<NELEM(predefs); i++) {
  1042.     n = predefs[i].token - F_OFFSET;
  1043.     if (n < 0 || n > NELEM(instrs))
  1044.         fatal("Token %s has illegal value %d.\n", predefs[i].word, n);
  1045.     instrs[n].min_arg = predefs[i].min_args;
  1046.     instrs[n].max_arg = predefs[i].max_args;
  1047.     instrs[n].name = predefs[i].word;
  1048.     instrs[n].type[0] = predefs[i].arg_type1;
  1049.     instrs[n].type[1] = predefs[i].arg_type2;
  1050.     instrs[n].Default = predefs[i].Default;
  1051.     instrs[n].ret_type = predefs[i].ret_type;
  1052.     instrs[n].arg_index = predefs[i].arg_index;
  1053.     }
  1054.     add_instr_name("<", F_LT);
  1055.     add_instr_name(">", F_GT);
  1056.     add_instr_name("<=", F_LE);
  1057.     add_instr_name(">=", F_GE);
  1058.     add_instr_name("==", F_EQ);
  1059.     add_instr_name("+=", F_ADD_EQ);
  1060.     add_instr_name("!", F_NOT);
  1061.     add_instr_name("index", F_INDEX);
  1062.     add_instr_name("push_indexed_lvalue", F_PUSH_INDEXED_LVALUE);
  1063.     add_instr_name("identifier", F_IDENTIFIER);
  1064.     add_instr_name("local", F_LOCAL_NAME);
  1065.     add_instr_name("indirect", F_INDIRECT);
  1066.     add_instr_name("number", F_NUMBER);
  1067.     add_instr_name("push_local_variable_lvalue", F_PUSH_LOCAL_VARIABLE_LVALUE);
  1068.     add_instr_name("const1", F_CONST1);
  1069.     add_instr_name("subtract", F_SUBTRACT);
  1070.     add_instr_name("assign", F_ASSIGN);
  1071.     add_instr_name("pop", F_POP_VALUE);
  1072.     add_instr_name("const0", F_CONST0);
  1073.     add_instr_name("jump_when_zero", F_JUMP_WHEN_ZERO);
  1074.     add_instr_name("jump_when_non_zero", F_JUMP_WHEN_NON_ZERO);
  1075.     add_instr_name("||", F_LOR);
  1076.     add_instr_name("&&", F_LAND);
  1077.     add_instr_name("-=", F_SUB_EQ);
  1078.     add_instr_name("jump", F_JUMP);
  1079.     add_instr_name("return", F_RETURN);
  1080.     add_instr_name("sscanf", F_SSCANF);
  1081.     add_instr_name("string", F_STRING);
  1082.     add_instr_name("call", F_CALL_FUNCTION_BY_ADDRESS);
  1083.     add_instr_name("aggregate", F_AGGREGATE);
  1084.     add_instr_name("m_aggregate", F_M_AGGREGATE);
  1085.     add_instr_name("push_identifier_lvalue", F_PUSH_IDENTIFIER_LVALUE);
  1086.     add_instr_name("+", F_ADD);
  1087.     add_instr_name("!=", F_NE);
  1088.     add_instr_name("dup", F_DUP);
  1089.     add_instr_name("catch", F_CATCH);
  1090.     add_instr_name("neg", F_NEGATE);
  1091.     add_instr_name("x++", F_POST_INC);
  1092.     add_instr_name("x--", F_POST_DEC);
  1093.     add_instr_name("switch",F_SWITCH);
  1094.     add_instr_name("break",F_BREAK);
  1095.     add_instr_name("range",F_RANGE);
  1096.     instrs[F_RANGE-F_OFFSET].type[0] = T_POINTER|T_STRING;
  1097. }
  1098.  
  1099. char *get_f_name(n)
  1100.     int n;
  1101. {
  1102.     if (instrs[n-F_OFFSET].name)
  1103.     return instrs[n-F_OFFSET].name;
  1104.     else {
  1105.     static char buf[30];
  1106.     sprintf(buf, "<OTHER %d>", n);
  1107.     return buf;
  1108.     }
  1109. }
  1110.  
  1111. static int
  1112. lookupword(s, words, h)
  1113. char *s;
  1114. struct keyword *words;
  1115. int h;
  1116. {
  1117.     int i, l, r;
  1118.  
  1119.     l = 0;
  1120.     for(;;) {
  1121.       i = (l+h)/2;
  1122.       r = strcmp(s, words[i].word);
  1123.       if (r == 0)
  1124.           return words[i].token;
  1125.       else if (l == i)
  1126.           return -1;
  1127.       else if (r < 0)
  1128.           h = i;
  1129.       else
  1130.           l = i;
  1131.     }
  1132. }
  1133.  
  1134. static int lookup_resword(s)
  1135.     char *s;
  1136. {
  1137.     return lookupword(s, reswords, NELEM(reswords));
  1138. }
  1139.  
  1140. int lookup_predef(s)
  1141.     char *s;
  1142. {
  1143.     return lookupword(s, predefs, NELEM(predefs));
  1144. }
  1145.  
  1146. #define NARGS 25
  1147. #define MARKS '@'
  1148.  
  1149. #define SKIPWHITE while(isspace(*p)) p++
  1150. #define GETALPHA(p, q, m) \
  1151.     while(isalunum(*p)) {\
  1152.     *q = *p++;\
  1153.     if (q < (m))\
  1154.         q++;\
  1155.     else {\
  1156.         lexerror("Name too long");\
  1157.         return;\
  1158.     }\
  1159.     }\
  1160.     *q++ = 0
  1161.  
  1162. static int
  1163. cmygetc()
  1164. {
  1165.     int c;
  1166.  
  1167.     for(;;) {
  1168.     c = mygetc();
  1169.     if (c == '/') {
  1170.         if (gobble('*'))
  1171.         skip_comment();
  1172.         else
  1173.         return c;
  1174.     } else
  1175.         return c;
  1176.     }
  1177. }
  1178.  
  1179. static void
  1180. refill()
  1181. {
  1182.     char *p;
  1183.     int c;
  1184.  
  1185.     p = yytext;
  1186.     do {
  1187.     c = cmygetc();
  1188.     if (p < yytext+MAXLINE-5)
  1189.         *p++ = c;
  1190.     else {
  1191.         lexerror("Line too long");
  1192.         break;
  1193.     }
  1194.     } while(c != '\n' && c != EOF);
  1195.     p[-1] = ' ';
  1196.     *p = 0;
  1197.     nexpands=0;
  1198.     current_line++;
  1199.     if (inctop == 0)
  1200.     store_line_number_info();
  1201. }
  1202.  
  1203. static void
  1204. handle_define(yyt)
  1205. char *yyt;
  1206. {
  1207.     char namebuf[NSIZE];
  1208.     char args[NARGS][NSIZE];
  1209.     char mtext[MLEN];
  1210.     char *p, *q;
  1211.  
  1212.     p = yyt;
  1213.     strcat(p, " ");
  1214.     q = namebuf;
  1215.     GETALPHA(p, q, namebuf+NSIZE-1);
  1216.     if (*p == '(') {        /* if "function macro" */
  1217.     int arg;
  1218.     int inid;
  1219.     char *ids;
  1220.     p++;            /* skip '(' */
  1221.     SKIPWHITE;
  1222.     if (*p == ')') {
  1223.         arg = 0;
  1224.     } else {
  1225.         for(arg = 0; arg < NARGS; ) {
  1226.         q = args[arg];
  1227.         GETALPHA(p, q, args[arg]+NSIZE-1);
  1228.         arg++;
  1229.         SKIPWHITE;
  1230.         if (*p == ')')
  1231.             break;
  1232.         if (*p++ != ',') {
  1233.             yyerror("Missing ',' in #define parameter list");
  1234.             return;
  1235.         }
  1236.         SKIPWHITE;
  1237.         }
  1238.         if (arg == NARGS) {
  1239.         lexerror("Too many macro arguments");
  1240.         return;
  1241.         }
  1242.     }
  1243.     p++;            /* skip ')' */
  1244.     for(inid = 0, q = mtext; *p; ) {
  1245.         if (isalunum(*p)) {
  1246.         if (!inid) {
  1247.             inid++;
  1248.             ids = p;
  1249.         }
  1250.         } else {
  1251.         if (inid) {
  1252.             int idlen = p - ids;
  1253.             int n, l;
  1254.             for(n = 0; n < arg; n++) {
  1255.             l = strlen(args[n]);
  1256.             if (l == idlen && strncmp(args[n], ids, l) == 0) {
  1257.                 q -= idlen;
  1258.                 *q++ = MARKS;
  1259.                 *q++ = n+MARKS+1;
  1260.                 break;
  1261.             }
  1262.             }
  1263.             inid = 0;
  1264.         }
  1265.         }
  1266.         *q = *p;
  1267.         if (*p++ == MARKS)
  1268.         *++q = MARKS;
  1269.         if (q < mtext+MLEN-2)
  1270.         q++;
  1271.         else {
  1272.         lexerror("Macro text too long");
  1273.         return;
  1274.         }
  1275.         if (!*p && p[-2] == '\\') {
  1276.         q -= 2;
  1277.         refill();
  1278.         p = yytext;
  1279.         }
  1280.     }
  1281.     *--q = 0;
  1282.     add_define(namebuf, arg, mtext);
  1283.     } else {
  1284.     for(q = mtext; *p; ) {
  1285.         *q = *p++;
  1286.         if (q < mtext+MLEN-2)
  1287.         q++;
  1288.         else {
  1289.         lexerror("Macro text too long");
  1290.         return;
  1291.         }
  1292.         if (!*p && p[-2] == '\\') {
  1293.         q -= 2;
  1294.         refill();
  1295.         p = yytext;
  1296.         }
  1297.     }
  1298.     *--q = 0;
  1299.     add_define(namebuf, -1, mtext);
  1300.     }
  1301.     return;
  1302. }
  1303.  
  1304. static void
  1305. myungetc(c)
  1306. int c;
  1307. {
  1308.     *--outp = c;
  1309.     nbuf++;
  1310. }
  1311.  
  1312. static void
  1313. add_input(p)
  1314. char *p;
  1315. {
  1316.     int l = strlen(p);
  1317.  
  1318. /*if (l > 2)
  1319. fprintf(stderr, "add '%s'\n", p);*/
  1320.     if (nbuf+l >= DEFMAX-10) {
  1321.     lexerror("Macro expansion buffer overflow");
  1322.     return;
  1323.     }
  1324.     outp -= l;
  1325.     nbuf += l;
  1326.     strncpy(outp, p, l);
  1327. }
  1328.  
  1329. #define DEFHASH 33
  1330. struct defn *defns[DEFHASH];
  1331. #define defhash(s) hashstr(s, 10, DEFHASH)
  1332.  
  1333. static void
  1334. add_define(name, nargs, exps)
  1335. char *name, *exps;
  1336. int nargs;
  1337. {
  1338.     struct defn *p;
  1339.     int h;
  1340.  
  1341.     if (p = lookup_define(name)) {
  1342.     if (nargs != p->nargs || strcmp(exps, p->exps) != 0) {
  1343.         char buf[200+NSIZE];
  1344.         sprintf(buf, "Redefinition of #define %s", name);
  1345.         yyerror(buf);
  1346.     }
  1347.     return;
  1348.     }
  1349.     p = (struct defn *)xalloc(sizeof(struct defn));
  1350.     p->name = xalloc(strlen(name)+1);
  1351.     strcpy(p->name, name);
  1352.     p->undef = 0;
  1353.     p->nargs = nargs;
  1354.     p->exps = xalloc(strlen(exps)+1);
  1355.     strcpy(p->exps, exps);
  1356.     h = defhash(name);
  1357.     p->next = defns[h];
  1358.     defns[h] = p;
  1359. /*fprintf(stderr, "define '%s' %d '%s'\n", name, nargs, exps);*/
  1360. }
  1361.  
  1362. void clear_defines()
  1363. {
  1364.     int i;
  1365.  
  1366.     for(i = 0; i < DEFHASH; i++)
  1367.         defns[i] = 0;
  1368.     nexpands = 0;
  1369. }
  1370.  
  1371. static void
  1372. free_defines()
  1373. {
  1374.     struct defn *p, *q;
  1375.     int i;
  1376.  
  1377.     for(i = 0; i < DEFHASH; i++) {
  1378.     for(p = defns[i]; p; p = q) {
  1379.         q = p->next;
  1380.         xfree(p->name);
  1381.         xfree(p->exps);
  1382.         xfree((char *)p);
  1383.     }
  1384.     defns[i] = 0;
  1385.     }
  1386.     nexpands = 0;
  1387. }
  1388.  
  1389. struct defn *
  1390. lookup_define(s)
  1391. char *s;
  1392. {
  1393.     struct defn *p;
  1394.     int h;
  1395.  
  1396.     h = defhash(s);
  1397.     for(p = defns[h]; p; p = p->next)
  1398.     if (!p->undef && strcmp(s, p->name) == 0)
  1399.         return p;
  1400.     return 0;
  1401. }
  1402.  
  1403. #define SKIPW \
  1404.         do {\
  1405.         c = cmygetc();\
  1406.     } while(isspace(c));
  1407.  
  1408.  
  1409. /* Check if yytext is a macro and expand if it is. */
  1410. static int
  1411. expand_define()
  1412. {
  1413.     struct defn *p;
  1414.     char expbuf[DEFMAX];
  1415.     char *args[NARGS];
  1416.     char buf[DEFMAX];
  1417.     char *q, *e, *b;
  1418.  
  1419.     if (nexpands++ > EXPANDMAX) {
  1420.     lexerror("Too many macro expansions");
  1421.     return 0;
  1422.     }
  1423.     p = lookup_define(yytext);
  1424.     if (!p) {
  1425.     return 0;
  1426.     }
  1427.     if (p->nargs == -1) {
  1428.     add_input(p->exps);
  1429.     } else {
  1430.     int c, parcnt = 0, dquote = 0, squote = 0;
  1431.     int n;
  1432.     SKIPW;
  1433.     if (c != '(') {
  1434.         yyerror("Missing '(' in macro call");
  1435.         return 0;
  1436.     }
  1437.     SKIPW;
  1438.     if (c == ')')
  1439.         n = 0;
  1440.     else {
  1441.         q = expbuf;
  1442.         args[0] = q;
  1443.         for(n = 0; n < NARGS; ) {
  1444.         switch(c) {
  1445.         case '"': if (!squote) dquote ^= 1; break;
  1446.         case '\'': if (!dquote) squote ^= 1; break;
  1447.         case '(': if (!squote && !dquote) parcnt++; break;
  1448.         case ')': if (!squote && !dquote) parcnt--; break;
  1449.         case '\\': if (squote || dquote) { *q++ = c; c = mygetc();} break;
  1450.         case '\n': if (squote || dquote) { lexerror("Newline in string"); return 0; } break;
  1451.         }
  1452.         if (c == ',' && !parcnt && !dquote && !squote) {
  1453.             *q++ = 0;
  1454.             args[++n] = q;
  1455.         } else if (parcnt < 0) {
  1456.             *q++ = 0;
  1457.             n++;
  1458.             break;
  1459.         } else {
  1460.             if (c == EOF) {
  1461.             lexerror("Unexpected end of file");
  1462.             return 0;
  1463.             }
  1464.             if (q >= expbuf + DEFMAX - 5) {
  1465.             lexerror("Macro argument overflow");
  1466.             return 0;
  1467.             } else {
  1468.             *q++ = c;
  1469.             }
  1470.         }
  1471.         if (!squote && ! dquote)
  1472.             c = cmygetc();
  1473.         else
  1474.             c = mygetc();
  1475.         }
  1476.         if (n == NARGS) {
  1477.         lexerror("Maximum macro argument count exceeded");
  1478.         return 0;
  1479.         }
  1480.     }
  1481.     if (n != p->nargs) {
  1482.         yyerror("Wrong number of macro arguments");
  1483.         return 0;
  1484.     }
  1485.     /* Do expansion */
  1486.     b = buf;
  1487.     e = p->exps;
  1488.     while(*e) {
  1489.         if (*e == MARKS) {
  1490.         if (*++e == MARKS)
  1491.             *b++ = *e++;
  1492.         else {
  1493.             for(q = args[*e++ - MARKS - 1]; *q; ) {
  1494.             *b++ = *q++;
  1495.             if (b >= buf+DEFMAX) {
  1496.                 lexerror("Macro expansion overflow");
  1497.                 return 0;
  1498.             }
  1499.             }
  1500.         }
  1501.         } else {
  1502.         *b++ = *e++;
  1503.         if (b >= buf+DEFMAX) {
  1504.             lexerror("Macro expansion overflow");
  1505.             return 0;
  1506.         }
  1507.         }
  1508.     }
  1509.     *b++ = 0;
  1510.     add_input(buf);
  1511.     }
  1512.     return 1;
  1513. }
  1514.  
  1515. /* Stuff to evaluate expression.  I havn't really checked it. /LA
  1516. ** Written by "J\"orn Rennecke" <amylaar@cs.tu-berlin.de>
  1517. */
  1518. #define SKPW     do c = mygetc(); while(isspace(c)); myungetc(c)
  1519.  
  1520. static int exgetc() {
  1521.   char c,*yyp;
  1522.  
  1523.   c = mygetc();
  1524.   while ( isalpha(c) || c=='_' ) {
  1525.     yyp=yytext;
  1526.     do {
  1527.       SAVEC;
  1528.       c = mygetc();
  1529.     } while ( isalunum(c) );
  1530.     myungetc(c);
  1531.     *yyp='\0';
  1532.     if (strcmp(yytext, "defined") == 0) {
  1533.     /* handle the defined "function" in #if */
  1534.     do c = mygetc(); while(isspace(c));
  1535.     if (c != '(') {
  1536.         yyerror("Missing ( in defined");
  1537.         continue;
  1538.     }
  1539.     do c = mygetc(); while(isspace(c));
  1540.     yyp=yytext;
  1541.     while ( isalunum(c) ) {
  1542.         SAVEC;
  1543.         c = mygetc();
  1544.     }
  1545.     *yyp='\0';
  1546.     while(isspace(c)) c = mygetc();
  1547.     if (c != ')') {
  1548.         yyerror("Missing ) in defined");
  1549.         continue;
  1550.     }
  1551.     SKPW;
  1552.     if (lookup_define(yytext))
  1553.         add_input(" 1 ");
  1554.     else
  1555.         add_input(" 0 ");
  1556.     } else {
  1557.     if (!expand_define()) add_input(" 0 ");
  1558.     }
  1559.     c = mygetc();
  1560.   }
  1561.   return c;
  1562. }
  1563.  
  1564. #define BNOT   1
  1565. #define LNOT   2
  1566. #define UMINUS 3
  1567. #define UPLUS  4
  1568.  
  1569. #define MULT   1
  1570. #define DIV    2
  1571. #define MOD    3
  1572. #define BPLUS  4
  1573. #define BMINUS 5
  1574. #define LSHIFT 6
  1575. #define RSHIFT 7
  1576. #define LESS   8
  1577. #define LEQ    9
  1578. #define GREAT 10
  1579. #define GEQ   11
  1580. #define EQ    12
  1581. #define NEQ   13
  1582. #define BAND  14
  1583. #define XOR   15
  1584. #define BOR   16
  1585. #define LAND  17
  1586. #define LOR   18
  1587. #define QMARK 19
  1588.  
  1589. static char _optab[]=
  1590. {0,4,0,0,0,26,56,0,0,0,18,14,0,10,0,22,0,0,0,0,0,0,0,0,0,0,0,0,30,50,40,74,
  1591. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,0,
  1592. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63,0,1};
  1593. static char optab2[]=
  1594. {BNOT,0,0,LNOT,'=',NEQ,7,0,0,UMINUS,0,BMINUS,10,UPLUS,0,BPLUS,10,
  1595. 0,0,MULT,11,0,0,DIV,11,0,0,MOD,11,
  1596. 0,'<',LSHIFT,9,'=',LEQ,8,0,LESS,8,0,'>',RSHIFT,9,'=',GEQ,8,0,GREAT,8,
  1597. 0,'=',EQ,7,0,0,0,'&',LAND,3,0,BAND,6,0,'|',LOR,2,0,BOR,4,
  1598. 0,0,XOR,5,0,0,QMARK,1};
  1599. #define optab1 (_optab-' ')
  1600.  
  1601. static int cond_get_exp(priority)
  1602. int priority;
  1603. {
  1604.   int c;
  1605.   int value,value2,x;
  1606.  
  1607.   do c=exgetc(); while ( isspace(c) );
  1608.   if ( c=='(' ) {
  1609.  
  1610.     value=cond_get_exp(0);
  1611.     do c=exgetc(); while ( isspace(c) );
  1612.     if ( c!=')' ) {
  1613.       yyerror("bracket not paired in #if");
  1614.       if (!c) myungetc('\0');
  1615.     }
  1616.   } else if ( ispunct(c) ) {
  1617.     x=optab1[c];
  1618.     if (!x) {
  1619.       yyerror("illegal character in #if");
  1620.       return 0;
  1621.     }
  1622.     value=cond_get_exp(12);
  1623.     switch ( optab2[x-1] ) {
  1624.       case BNOT  : value = ~value; break;
  1625.       case LNOT  : value = !value; break;
  1626.       case UMINUS: value = -value; break;
  1627.       case UPLUS : value =  value; break;
  1628.       default :
  1629.     yyerror("illegal unary operator in #if");
  1630.     return 0;
  1631.     }
  1632.   } else {
  1633.     int base;
  1634.  
  1635.     if ( !isdigit(c) ) {
  1636.       if (!c) {
  1637.     yyerror("missing expression in #if");
  1638.     myungetc('\0');
  1639.       } else yyerror("illegal character in #if");
  1640.       return 0;
  1641.     }
  1642.     value=0;
  1643.     if ( c!='0' ) base=10;
  1644.     else {
  1645.       c = mygetc();
  1646.       if ( c=='x' || c=='X' ) {
  1647.     base=16;
  1648.     c = mygetc();
  1649.       } else base=8;
  1650.     }
  1651.     for(;;) {
  1652.       if ( isdigit(c) ) x = -'0';
  1653.       else if ( isupper(c) ) x = -'A'+10;
  1654.       else if ( islower(c) ) x = -'a'+10;
  1655.       else break;
  1656.       x+=c;
  1657.       if ( x > base ) break;
  1658.       value=value*base+x;
  1659.       c = mygetc();
  1660.     }
  1661.     myungetc(c);
  1662.   }
  1663.   for (;;) {
  1664.     do c=exgetc(); while ( isspace(c) );
  1665.     if ( !ispunct(c) ) break;
  1666.     x=optab1[c];
  1667.     if (!x) break;
  1668.     value2 = mygetc();
  1669.     for(;;x+=3) {
  1670.       if ( !optab2[x] ) {
  1671.     myungetc(value2);
  1672.     if ( !optab2[x+1] ) {
  1673.       yyerror("illegal operator use in #if");
  1674.       return 0;
  1675.     }
  1676.     break;
  1677.       }
  1678.       if ( value2==optab2[x] ) break;
  1679.     }
  1680.     if ( priority >= optab2[x+2] ) {
  1681.       if( optab2[x] ) myungetc(value2);
  1682.       break;
  1683.     }
  1684.     value2=cond_get_exp(optab2[x+2]);
  1685.     switch ( optab2[x+1] ) {
  1686.       case MULT : value *= value2;    break;
  1687.       case DIV  :
  1688.       {
  1689.           if (!value2) {
  1690.               yyerror("division by zero");
  1691.         } else {
  1692.             value /= value2;
  1693.         }
  1694.         break;
  1695.       }
  1696.       case MOD  : value %= value2;    break;
  1697.       case BPLUS  : value += value2;    break;
  1698.       case BMINUS : value -= value2;    break;
  1699.       case LSHIFT : value <<= value2;    break;
  1700.       case RSHIFT : value >>= value2;    break;
  1701.       case LESS   : value = value <  value2;    break;
  1702.       case LEQ    : value = value <= value2;    break;
  1703.       case GREAT  : value = value >  value2;    break;
  1704.       case GEQ    : value = value >= value2;    break;
  1705.       case EQ     : value = value == value2;    break;
  1706.       case NEQ    : value = value != value2;    break;
  1707.       case BAND   : value &= value2;    break;
  1708.       case XOR    : value ^= value2;    break;
  1709.       case BOR    : value |= value2;    break;
  1710.       case LAND   : value = value && value2;    break;
  1711.       case LOR    : value = value || value2;    break;
  1712.       case QMARK  :
  1713.     do c=exgetc(); while( isspace(c) );
  1714.     if ( c!=':' ) {
  1715.       yyerror("'?' without ':' in #if");
  1716.       myungetc(c);
  1717.       return 0;
  1718.     }
  1719.     if ( value ) {
  1720.       cond_get_exp(1);
  1721.       value=value2;
  1722.     }
  1723.     else value=cond_get_exp(1);
  1724.     break;
  1725.     }
  1726.   }
  1727.   myungetc(c);
  1728.   return value;
  1729. }
  1730.  
  1731. void set_inc_list(sv)
  1732.     struct svalue *sv;
  1733. {
  1734.     int i;
  1735.     struct vector *v;
  1736.     char *p;
  1737.  
  1738.     if (sv == 0) {
  1739.         fprintf(stderr, "There must be a function 'define_include_dirs' in master.c.\n");
  1740.         fprintf(stderr, "This function should return an array of all directories to be searched\n");
  1741.         fprintf(stderr, "for include files.\n");
  1742.         LPExit(1);
  1743.     }
  1744.     if (sv->type != T_POINTER) {
  1745.         fprintf(stderr, "'define_include_dirs' in master.c did not return an array.\n");
  1746.         LPExit(1);
  1747.     }
  1748.     v = sv->u.vec;
  1749.     inc_list = (char **)xalloc(v->size * sizeof (char *));
  1750.     inc_list_size = v->size;
  1751.     for (i=0; i < v->size; i++) {
  1752.     if (v->item[i].type != T_STRING) {
  1753.         fprintf(stderr, "Illegal value returned from 'define_include_dirs' in master.c\n");
  1754.         LPExit(1);
  1755.     }
  1756.     p = v->item[i].u.string;
  1757.     if (*p == '/')
  1758.         p++;
  1759.     /*
  1760.      * Even make sure that the game administrator has not made an error.
  1761.      */
  1762.     if (!legal_path(p)) {
  1763.         fprintf(stderr, "'define_include_dirs' must give paths without any '..'\n");
  1764.         LPExit(1);
  1765.     }
  1766.     inc_list[i] = make_shared_string(p);
  1767.     }
  1768. }
  1769.